/*
 * @Description: 
 * @Author: fhw
 * @Date: 2023-03-06 10:48:47
 */
import { ref } from 'vue'
import { diff as diffJson, DiffEdit, DiffArray } from 'deep-diff'
import { equals, head, isEmpty, isNil, last } from 'ramda'
import { isNumber } from '@/utils/tools'
function hdE(data: DiffEdit<any, any>) {
    if (data.path) {
        const isArray = data.path.some((res) => isNumber(res))
        if (isArray && data.path.length === 3) {
            return {
                type: 'edit-array',
                name: head(data.path),
                field: last(data.path),
                index: data.path[1],
                lhs: data.lhs,
                rhs: data.rhs
            }
        } else {
            return {
                type: equals(data.path.length, 1) ? 'first-object' : 'second-object',
                name: data.path?.join('.'),
                lhs: data.lhs,
                rhs: data.rhs
            }
        }
    }
}

function hdA(data: DiffArray<any>) {
    return data.item.kind === 'N'
        ? {
            type: 'add-array',
            name: data.path?.join('.'),
            index: data.index,
            lhs: {},
            rhs: data.item.rhs
        }
        : {
            type: 'delete-array',
            name: data.path?.join('.'),
            index: data.index,
            lhs: {},
            rhs: {}
        }
}
export function useDiff<T>(filterStr?: string[]) {
    const lhs = ref<T>()
    const filterkeys = filterStr
    function filter(path: any[], key: any) {
        // console.log(path, key)
        if (!isEmpty(path) && isNumber(key)) {
            return false
        }
        if (isNil(filterkeys)) {
            return false
        }
        return !filterkeys.includes(key)
    }
    const diff = <P>(rhs: P) => {
        const diffStr = diffJson(lhs.value, rhs, filterkeys ? filter : undefined)
        if (diffStr) {
            return diffStr.map((data) => {
                switch (data.kind) {
                    case 'E':
                        return hdE(data)
                    case 'A':
                        return hdA(data)
                    default:
                        break
                }
            })
        }
        return undefined
    }

    return {
        lhs,
        diff
    }
}
